package com.ruoyi.system.common;

import com.ruoyi.common.utils.DateUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;
import java.util.List;
import java.util.UUID;

public abstract class BaseInsertService<T> {

    @Transactional(rollbackFor = Exception.class)
    public int insertEntity(T entity) {
        // 1️⃣ 参数校验
        validateBeforeInsert(entity);

        // 2️⃣ 查重逻辑（提高用户体验）
        if (existsByUniqueField(entity)) {
            throw new IllegalArgumentException("数据已存在：" + getUniqueFieldValue(entity));
        }

        // 3️⃣ 设置主键与时间
        setIdAndCreateTime(entity);

        // 4️⃣ 生成业务编号（若需要）
        setBusinessCodeIfAbsent(entity);

        // 5️⃣ 执行插入 + 异常兜底
        try {
            return doInsert(entity);
        } catch (DuplicateKeyException e) {
            handleDuplicateKey(e, entity);
            throw new RuntimeException("插入失败，唯一约束冲突", e);
        }
    }

    // --- 允许子类覆盖 ---
    protected void setIdAndCreateTime(T entity) {
        try {
            // 使用反射为 entity 设置 ID（如果有 setId 方法）
            Method setId = entity.getClass().getMethod("setId", String.class);
            setId.invoke(entity, UUID.randomUUID().toString().replace("-", ""));

            // 使用反射为 entity 设置创建时间（如果有 setCreateTime 方法）
            Method setCreateTime = entity.getClass().getMethod("setCreateTime", java.util.Date.class);
            setCreateTime.invoke(entity, DateUtils.getNowDate());
        } catch (Exception ignored) {
            // 如果没有对应字段或方法，就跳过
        }
    }


    // ===== 以下抽象方法交由子类实现 =====
    protected abstract void validateBeforeInsert(T entity);// 参数校验
    protected abstract boolean existsByUniqueField(T entity);// 查重逻辑
    protected abstract Object getUniqueFieldValue(T entity);// 获取唯一字段的值
//    protected abstract void setIdAndCreateTime(T entity);
    protected abstract void setBusinessCodeIfAbsent(T entity);// 设置业务编号（若需要）
    protected abstract int doInsert(T entity);// 执行插入
    protected abstract void handleDuplicateKey(DuplicateKeyException e, T entity);// 处理唯一键冲突
}
